package com.smart.tool.scheduler;


import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * * @Author xiaoqiang
 * * @Version TaskConfig.java, v 0.1 2025年08月17日 08:25 xiaoqiang
 * * @Description: TODO
 * 调度任务的配置类，使用 Builder 模式构建。
 */
public class TaskConfig<T> {
    // 必填
    private final String taskKey;
    private final Task<T> task;

    // 选填
    private final TaskType type;
    private final long initialDelay; // 默认为0，表示无初始延迟，立即执行
    private final TimeUnit delayUnit; // 默认为 MILLISECONDS
    private final long interval; // 对于 FIBONACCI_INTERVAL，这可以作为初始间隔或步长
    private final TimeUnit intervalUnit; // 默认为 MILLISECONDS
    private final String cronExpression;
    private final int maxExecutions; // -1 表示无限
    private final TaskCallback<T> callback;

    private TaskConfig(Builder builder) {
        this.taskKey = Objects.requireNonNull(builder.taskKey, "taskKey is required");
        this.task = Objects.requireNonNull(builder.task, "task is required");
        this.type = Objects.requireNonNullElse(builder.type, TaskType.ONE_TIME);
        this.initialDelay = builder.initialDelay; // 默认值已在 Builder 中设置
        this.delayUnit = Objects.requireNonNullElse(builder.delayUnit, TimeUnit.MILLISECONDS);
        this.interval = builder.interval;
        this.intervalUnit = Objects.requireNonNullElse(builder.intervalUnit, TimeUnit.MILLISECONDS);
        this.cronExpression = builder.cronExpression;
        this.maxExecutions = builder.maxExecutions;
        this.callback = builder.callback;

        // 参数校验
        validate();
    }

    private void validate() {
        if (type == TaskType.CRON && (cronExpression == null || cronExpression.trim().isEmpty())) {
            throw new IllegalArgumentException("Cron expression is required for CRON task type");
        }
        if ((type == TaskType.FIXED_INTERVAL || type == TaskType.FIBONACCI_INTERVAL) && interval <= 0) {
            throw new IllegalArgumentException("Interval must be positive for " + type);
        }
        // 初始延迟可以为0，表示立即执行，但不能为负数
        if (initialDelay < 0) {
            throw new IllegalArgumentException("Initial delay cannot be negative");
        }
    }

    // Getter 方法
    public String getTaskKey() {
        return taskKey;
    }

    public Task<T> getTask() {
        return task;
    }

    public TaskType getType() {
        return type;
    }

    public long getInitialDelay() {
        return initialDelay;
    }

    public TimeUnit getDelayUnit() {
        return delayUnit;
    }

    public long getInterval() {
        return interval;
    }

    public TimeUnit getIntervalUnit() {
        return intervalUnit;
    }

    public String getCronExpression() {
        return cronExpression;
    }

    public int getMaxExecutions() {
        return maxExecutions;
    }

    public TaskCallback getCallback() {
        return callback;
    }


    // --- Builder ---
    public static class Builder<T> {
        private String taskKey;
        private Task<T> task;
        private TaskType type;
        private long initialDelay = 0; // 默认无初始延迟，任务立即执行
        private TimeUnit delayUnit;
        private long interval;
        private TimeUnit intervalUnit;
        private String cronExpression;
        private int maxExecutions = -1; // -1 表示无限次执行
        private TaskCallback<T> callback;

        private Builder() {
        }

        public Builder taskKey(String taskKey) {
            this.taskKey = taskKey;
            return this;
        }

        public Builder task(Task<T> task) {
            this.task = task;
            return this;
        }

        public Builder type(TaskType type) {
            this.type = type;
            return this;
        }

        /**
         * 设置任务的初始延迟。
         * 如果不调用此方法，则 initialDelay 默认为 0，表示任务在调度时立即尝试执行。
         *
         * @param delay 延迟时间
         * @param unit  延迟时间单位
         * @return Builder 实例
         */
        public Builder initialDelay(long delay, TimeUnit unit) {
            this.initialDelay = delay;
            this.delayUnit = unit;
            return this;
        }

        public Builder interval(long interval, TimeUnit unit) {
            this.interval = interval;
            this.intervalUnit = unit;
            return this;
        }

        public Builder cronExpression(String cronExpression) {
            this.cronExpression = cronExpression;
            this.type = TaskType.CRON; // 设置类型为 CRON
            return this;
        }

        public Builder maxExecutions(int maxExecutions) {
            this.maxExecutions = maxExecutions;
            return this;
        }

        public Builder callback(TaskCallback<T> callback) {
            this.callback = callback;
            return this;
        }

        public TaskConfig build() {
            return new TaskConfig(this);
        }
    }


    /**
     * 创建一个立即执行的一次性任务配置。
     *
     * @param taskKey 任务编码 可以为 null
     * @param task    要执行的任务
     * @return TaskConfig 实例
     */
    public static TaskConfig oneTime(String taskKey,
                                     RunnableTask task,
                                     TaskCallback callback) {
        if (task == null) {
            throw new IllegalArgumentException("task is null");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .initialDelay(0, TimeUnit.MILLISECONDS)
                .type(TaskType.ONE_TIME)
                .callback(callback)
                .build();
    }

    /**
     * 创建一个带初始延迟的一次性任务配置。
     *
     * @param taskKey      任务编码 可以为 null
     * @param task         要执行的任务
     * @param initialDelay 初始延迟时间
     * @param delayUnit    初始延迟时间单位
     * @return TaskConfig 实例
     */
    public static TaskConfig oneTime(String taskKey,
                                     long initialDelay,
                                     TimeUnit delayUnit,
                                     RunnableTask task,
                                     TaskCallback callback) {
        if (task == null) {
            throw new IllegalArgumentException("task is null");
        }
        if (initialDelay < 0) {
            throw new IllegalArgumentException("initialDelay must be positive");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.ONE_TIME)
                .callback(callback)
                .initialDelay(initialDelay, delayUnit)
                .build();
    }

    // --- 便捷方法：固定频率任务 ---

    /**
     * 创建一个立即开始执行的固定频率任务配置。
     *
     * @param taskKey       任务编码 可以为 null
     * @param task          要执行的任务
     * @param interval      执行间隔
     * @param unit          执行间隔单位
     * @param maxExecutions 最大执行次数， , 小于等于0为无限次调度
     * @return TaskConfig 实例
     */
    public static TaskConfig fixedRate(String taskKey,
                                       long interval, TimeUnit unit, int maxExecutions, RunnableTask task, TaskCallback callback) {
        if (task == null) {
            throw new IllegalArgumentException("task is null");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.FIXED_INTERVAL)
                .maxExecutions(maxExecutions == 0 ? -1 : maxExecutions)
                .callback(callback)
                .interval(interval, unit)
                .initialDelay(0, unit) // 明确设置无初始延迟
                .build();
    }

    /**
     * 创建一个带初始延迟的固定频率任务配置。
     *
     * @param taskKey       任务编码 可以为 null
     * @param task          要执行的任务
     * @param initialDelay  初始延迟时间
     * @param delayUnit     初始延迟时间单位
     * @param interval      执行间隔
     * @param intervalUnit  执行间隔单位
     * @param maxExecutions 最大执行次数， , 小于等于0是无限次调度
     * @return TaskConfig 实例
     *
     */
    public static TaskConfig fixedRate(String taskKey,
                                       long initialDelay, TimeUnit delayUnit,
                                       long interval, TimeUnit intervalUnit
            , int maxExecutions, RunnableTask task, TaskCallback callback) {
        if (task == null) {
            throw new IllegalArgumentException("task is null");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.FIXED_INTERVAL)
                .maxExecutions(maxExecutions == 0 ? -1 : maxExecutions)
                .callback(callback)
                .initialDelay(initialDelay, delayUnit)
                .interval(interval, intervalUnit)
                .build();
    }

    // --- 便捷方法：斐波那契间隔任务 ---

    /**
     * 创建一个立即开始执行的斐波那契间隔任务配置。
     *
     * @param taskKey         任务编码 可以为 null
     * @param task            要执行的任务
     * @param initialInterval 斐波那契序列的初始间隔（也是第一步的间隔）
     * @param unit            间隔单位
     * @param maxExecutions   最大执行次数， , 小于等于0是无限次调度
     * @return TaskConfig 实例
     */
    public static TaskConfig fibonacciInterval(String taskKey,

                                               long initialInterval,
                                               TimeUnit unit
            , int maxExecutions
            , RunnableTask task
            , TaskCallback callback) {
        if (task == null) {
            throw new IllegalArgumentException("task is null");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.FIBONACCI_INTERVAL)
                .interval(initialInterval, unit) // interval 代表初始步长
                .initialDelay(0, unit) // 明确设置无初始延迟
                .maxExecutions(maxExecutions == 0 ? -1 : maxExecutions)
                .callback(callback)
                .build();
    }

    /**
     * 创建一个带初始延迟的斐波那契间隔任务配置。
     *
     * @param taskKey         任务编码 可以为 null
     * @param task            要执行的任务
     * @param initialDelay    初始延迟时间
     * @param delayUnit       初始延迟时间单位
     * @param initialInterval 斐波那契序列的初始间隔（也是第一步的间隔）
     * @param intervalUnit    间隔单位
     * @param maxExecutions   最大执行次数， , 小于等于0是无限次调度
     * @return TaskConfig 实例
     */
    public static TaskConfig fibonacciInterval(String taskKey,
                                               long initialDelay, TimeUnit delayUnit,
                                               long initialInterval, TimeUnit intervalUnit, int maxExecutions
            , RunnableTask task, TaskCallback callback) {
        if (initialInterval <= 0) {
            throw new IllegalArgumentException("initialInterval is less than 0");
        }
        if (maxExecutions <= 0) {
            throw new IllegalArgumentException("maxExecutions is less than 0");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.FIBONACCI_INTERVAL)
                .initialDelay(initialDelay, delayUnit)
                .interval(initialInterval, intervalUnit) // interval 代表初始步长
                .maxExecutions(maxExecutions == 0 ? -1 : maxExecutions)
                .callback(callback)
                .build();
    }

    /**
     * backOffInterval 方法用于创建带初始延迟的任务配置。
     *
     * @param taskKey         任务编码 可以为 null
     * @param task            要执行的任务
     * @param initialDelay    初始延迟时间
     * @param delayUnit       初始延迟时间单位
     * @param initialInterval 任务的初始间隔
     * @param intervalUnit    间隔单位
     * @param maxExecutions   最大执行次数， , 小于等于0是无限次调度 ，
     * @return TaskConfig 实例
     */
    public static TaskConfig backOffInterval(String taskKey,
                                             long initialDelay, TimeUnit delayUnit,
                                             long initialInterval, TimeUnit intervalUnit, int maxExecutions
            , RunnableTask task, TaskCallback callback) {

        if (initialInterval < 0) {
            throw new IllegalArgumentException("initialInterval is less than 0");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.BACK_OFF)
                .initialDelay(initialDelay, delayUnit)
                .interval(initialInterval, intervalUnit) // interval 代表初始步长
                .maxExecutions(maxExecutions == 0 ? -1 : maxExecutions)
                .callback(callback)
                .build();
    }


    // --- 便捷方法：Cron 表达式任务 ---

    /**
     * 创建一个立即开始根据 Cron 表达式执行的任务配置。支持 6 位或 7 位的 Cron 表达式
     *
     * @param taskKey        任务编码 可以为 null
     * @param task           要执行的任务
     * @param cronExpression Cron 表达式
     * @return TaskConfig 实例
     */
    public static TaskConfig cron(String taskKey, String cronExpression, RunnableTask task, TaskCallback callback) {

        if (cronExpression == null) {
            throw new IllegalArgumentException("cronExpression is null");
        }

        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.CRON)
                .cronExpression(cronExpression)
                .initialDelay(0, TimeUnit.MILLISECONDS) // 明确设置无初始延迟
                .callback(callback)
                .build();
    }
    // --- 便捷方法：Cron 表达式任务 ---

    /**
     * 创建一个立即开始根据 Cron 表达式执行的任务配置。支持 6 位或 7 位的 Cron 表达式
     *
     * @param taskKey        任务编码 可以为 null
     * @param task           要执行的任务
     * @param maxExecutions  任务执行的最大次数，小于等于  0 表示无限次
     * @param cronExpression Cron 表达式
     * @return TaskConfig 实例
     */
    public static TaskConfig cron(String taskKey, String cronExpression, int maxExecutions, RunnableTask task, TaskCallback callback) {
        if (cronExpression == null) {
            throw new IllegalArgumentException("cronExpression is null");
        }

        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.CRON)
                .maxExecutions(maxExecutions)
                .cronExpression(cronExpression)
                .initialDelay(0, TimeUnit.MILLISECONDS) // 明确设置无初始延迟
                .callback(callback)
                .build();
    }

    /**
     * 创建一个立即执行的一次性任务配置。
     *
     * @param taskKey 任务编码 可以为 null
     * @param task    要执行的任务
     * @return TaskConfig 实例
     */
    public static <T> TaskConfig oneTimeWithResult(String taskKey,
                                                   CallableTask<T> task,
                                                   TaskCallback<T> callback) {
        if (task == null) {
            throw new IllegalArgumentException("task is null");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .maxExecutions(1)
                .initialDelay(0, TimeUnit.MILLISECONDS)
                .type(TaskType.ONE_TIME)
                .callback(callback)
                .build();
    }

    /**
     * 创建一个带初始延迟的一次性任务配置。
     *
     * @param taskKey      任务编码 可以为 null
     * @param task         要执行的任务
     * @param initialDelay 初始延迟时间
     * @param delayUnit    初始延迟时间单位
     * @return TaskConfig 实例
     */
    public static <T> TaskConfig oneTimeWithResult(String taskKey,
                                                   long initialDelay,
                                                   TimeUnit delayUnit,
                                                   CallableTask<T> task,
                                                   TaskCallback<T> callback) {
        if (task == null) {
            throw new IllegalArgumentException("task is null");
        }
        if (initialDelay < 0) {
            throw new IllegalArgumentException("initialDelay must be positive");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.ONE_TIME)
                .callback(callback)
                .initialDelay(initialDelay, delayUnit)
                .build();
    }

    // --- 便捷方法：固定频率任务 ---

    /**
     * 创建一个立即开始执行的固定频率任务配置。
     *
     * @param taskKey       任务编码 可以为 null
     * @param task          要执行的任务
     * @param interval      执行间隔
     * @param unit          执行间隔单位
     * @param maxExecutions 最大执行次数， , 小于等于0为无限次调度
     * @return TaskConfig 实例
     */
    public static <T> TaskConfig fixedRateWithResult(String taskKey,
                                                     long interval,
                                                     TimeUnit unit,
                                                     int maxExecutions,
                                                     CallableTask<T> task,
                                                     TaskCallback<T> callback) {
        if (task == null) {
            throw new IllegalArgumentException("task is null");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.FIXED_INTERVAL)
                .maxExecutions(maxExecutions == 0 ? -1 : maxExecutions)
                .callback(callback)
                .interval(interval, unit)
                .initialDelay(0, unit) // 明确设置无初始延迟
                .build();
    }

    /**
     * 创建一个带初始延迟的固定频率任务配置。
     *
     * @param taskKey       任务编码 可以为 null
     * @param task          要执行的任务
     * @param initialDelay  初始延迟时间
     * @param delayUnit     初始延迟时间单位
     * @param interval      执行间隔
     * @param intervalUnit  执行间隔单位
     * @param maxExecutions 最大执行次数， , 小于等于0是无限次调度
     * @return TaskConfig 实例
     *
     */
    public static <T> TaskConfig fixedRateWithResult(String taskKey,
                                                     long initialDelay, TimeUnit delayUnit,
                                                     long interval, TimeUnit intervalUnit
            , int maxExecutions, CallableTask<T> task,
                                                     TaskCallback<T> callback) {
        if (task == null) {
            throw new IllegalArgumentException("task is null");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.FIXED_INTERVAL)
                .maxExecutions(maxExecutions == 0 ? -1 : maxExecutions)
                .callback(callback)
                .initialDelay(initialDelay, delayUnit)
                .interval(interval, intervalUnit)
                .build();
    }

    // --- 便捷方法：斐波那契间隔任务 ---

    /**
     * 创建一个立即开始执行的斐波那契间隔任务配置。
     *
     * @param taskKey         任务编码 可以为 null
     * @param task            要执行的任务
     * @param initialInterval 斐波那契序列的初始间隔（也是第一步的间隔）
     * @param unit            间隔单位
     * @param maxExecutions   最大执行次数， , 小于等于0是无限次调度
     * @return TaskConfig 实例
     */
    public static <T> TaskConfig fibonacciIntervalWithResult(String taskKey,

                                                             long initialInterval,
                                                             TimeUnit unit
            , int maxExecutions
            , CallableTask<T> task,
                                                             TaskCallback<T> callback) {
        if (task == null) {
            throw new IllegalArgumentException("task is null");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.FIBONACCI_INTERVAL)
                .interval(initialInterval, unit) // interval 代表初始步长
                .initialDelay(0, unit) // 明确设置无初始延迟
                .maxExecutions(maxExecutions == 0 ? -1 : maxExecutions)
                .callback(callback)
                .build();
    }

    /**
     * 创建一个带初始延迟的斐波那契间隔任务配置。
     *
     * @param taskKey         任务编码 可以为 null
     * @param task            要执行的任务
     * @param initialDelay    初始延迟时间
     * @param delayUnit       初始延迟时间单位
     * @param initialInterval 斐波那契序列的初始间隔（也是第一步的间隔）
     * @param intervalUnit    间隔单位
     * @param maxExecutions   最大执行次数， , 小于等于0是无限次调度
     * @return TaskConfig 实例
     */
    public static <T> TaskConfig fibonacciIntervalWithResult(String taskKey,
                                                             long initialDelay, TimeUnit delayUnit,
                                                             long initialInterval, TimeUnit intervalUnit, int maxExecutions
            ,CallableTask<T> task,
                                                             TaskCallback<T> callback) {
        if (initialInterval <= 0) {
            throw new IllegalArgumentException("initialInterval is less than 0");
        }
        if (maxExecutions <= 0) {
            throw new IllegalArgumentException("maxExecutions is less than 0");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.FIBONACCI_INTERVAL)
                .initialDelay(initialDelay, delayUnit)
                .interval(initialInterval, intervalUnit) // interval 代表初始步长
                .maxExecutions(maxExecutions == 0 ? -1 : maxExecutions)
                .callback(callback)
                .build();
    }

    /**
     * backOffInterval 方法用于创建带初始延迟的任务配置。
     *
     * @param taskKey         任务编码 可以为 null
     * @param task            要执行的任务
     * @param initialDelay    初始延迟时间
     * @param delayUnit       初始延迟时间单位
     * @param initialInterval 任务的初始间隔
     * @param intervalUnit    间隔单位
     * @param maxExecutions   最大执行次数， , 小于等于0是无限次调度 ，
     * @return TaskConfig 实例
     */
    public static <T> TaskConfig backOffIntervalWithResult(String taskKey,
                                                           long initialDelay,
                                                           TimeUnit delayUnit,
                                                           long initialInterval,
                                                           TimeUnit intervalUnit,
                                                           int maxExecutions,
                                                           CallableTask<T> task,
                                                           TaskCallback<T> callback) {

        if (initialInterval < 0) {
            throw new IllegalArgumentException("initialInterval is less than 0");
        }
        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.BACK_OFF)
                .initialDelay(initialDelay, delayUnit)
                .interval(initialInterval, intervalUnit) // interval 代表初始步长
                .maxExecutions(maxExecutions == 0 ? -1 : maxExecutions)
                .callback(callback)
                .build();
    }


    // --- 便捷方法：Cron 表达式任务 ---

    /**
     * 创建一个立即开始根据 Cron 表达式执行的任务配置。支持 6 位或 7 位的 Cron 表达式
     *
     * @param taskKey        任务编码 可以为 null
     * @param task           要执行的任务
     * @param cronExpression Cron 表达式
     * @return TaskConfig 实例
     */
    public static <T> TaskConfig cronWithResult(String taskKey,
                                                String cronExpression,
                                                CallableTask<T> task,
                                                TaskCallback<T> callback) {

        if (cronExpression == null) {
            throw new IllegalArgumentException("cronExpression is null");
        }

        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.CRON)
                .cronExpression(cronExpression)
                .initialDelay(0, TimeUnit.MILLISECONDS) // 明确设置无初始延迟
                .callback(callback)
                .build();
    }
    // --- 便捷方法：Cron 表达式任务 ---

    /**
     * 创建一个立即开始根据 Cron 表达式执行的任务配置。支持 6 位或 7 位的 Cron 表达式
     *
     * @param taskKey        任务编码 可以为 null
     * @param task           要执行的任务
     * @param maxExecutions  任务执行的最大次数，小于等于  0 表示无限次
     * @param cronExpression Cron 表达式
     * @return TaskConfig 实例
     */
    public static <T> TaskConfig cronWithResult(String taskKey,
                                                String cronExpression,
                                                int maxExecutions,
                                                CallableTask<T> task,
                                                TaskCallback<T> callback) {
        if (cronExpression == null) {
            throw new IllegalArgumentException("cronExpression is null");
        }

        return new Builder()
                .taskKey(taskKey)
                .task(task)
                .type(TaskType.CRON)
                .maxExecutions(maxExecutions)
                .cronExpression(cronExpression)
                .initialDelay(0, TimeUnit.MILLISECONDS) // 明确设置无初始延迟
                .callback(callback)
                .build();
    }
}
